#include "simulation.h"
#include <iterator>
#include <iostream>
#include <vector>
#include <algorithm>
FCFSSimulation::FCFSSimulation(int argc, char **argv) : Simulation(argc, argv) {
}

//schedule a departure event for a given customer
void FCFSSimulation::schedule_departure(Customer *customer) {

    for (uint32_t index = 0; index < event_list.size(); ++index) {
        if (event_list[index]->customer_->id_ == customer->id_ &&
            event_list[index]->type_ == 'D') {
            return;
        }
    }
    //set the service time
    if (m == 0) {
        Ts = expntl(1/mu, kSeed_service);
    } else if (m == 1) {
        Ts = pareto(&kSeed_service);
    }
    customer->service_time_ = Ts;
    //create a departure event and add it to the event list
    EventNode *current_departure = new EventNode('D', customer, sim_time + Ts);
    event_list_add(current_departure);
}

//process an arrival event
void FCFSSimulation::process_arrival(EventNode *next_event) {
    //generate the next inter-arrival time
    Ta = expntl(1/lambda, kSeed_arrival);
    //set the simulation time to the time of the next event
    sim_time = next_event->time_;
    arrival_count++;
    customer_queue.push_back(next_event->customer_);
    n++;
    if (n <= numservers) {
        for (uint32_t index = 0; index < n; ++index) {
            Customer *current = customer_queue[index];
            current->server_id_ = index;
            schedule_departure(current);
        }
    }
    Customer *customer = new Customer(total_arrival_count++, sim_time + Ta, 0, 0, 0, false, false); 
    customer_list.push_back(customer);
    EventNode *next_arrival = new EventNode('A', customer, sim_time + Ta);
    event_list_add(next_arrival);
}

void FCFSSimulation::process_departure(EventNode *next_event) {
    if (! customer_queue.empty()) {
        Customer *departing_customer = next_event->customer_;
        sim_time = next_event->time_;
        departing_customer->departure_time_ = sim_time;
        departing_customer->serviced_ = true;
        departing_customer->lost_ = false;
        departing_customer->departure_number_ = ++departure_count;
        customer_queue.erase(customer_queue.begin() + departing_customer->server_id_);
        departing_customer->customers_after_ = customer_queue.size();
        n--;
        serve_count++;
        if (n > 0) {
            uint32_t min_value = n < numservers ? n : numservers;
            for (uint32_t index = 0; index < min_value; ++index) {
                Customer *current = customer_queue[index];
                current->server_id_ = index;
                schedule_departure(current);
            }
        }
    } 
}

void FCFSSimulation::print_queues() {
    for (uint32_t index = 0; index < customer_queue.size(); ++index) {
        cout << customer_queue[index]->id_ << " ";
    }
    cout << endl;
}
